Updating qb-policejob
Because r14-evidence uses many of the event names as qb-policejob to maintain compatability with existing
resources, we will need to remove the existing code which provides for evidence generation and handling
from the qb-policejob/client/evidence.lua
and qb-policejob/server/main.lua
files. Additionally,
if you have resources which are clones of qb-policejob
, such as qb-fib
, you will need to repeat
this process for those as well! You do not need multiple versions of evidence per job, and can instead include
all jobs that need access to evidence under the included Config.AuthorizedJobs.LEO
table.
Never make changes to ANY script without making a backup first, you never know what might happen!
Deleting Existing Evidence Files
The first step of our process will be simply deleting the qb-policejob/client/evidence.lua
file from our
resource, this will prevent the duplication of evidence creation when firing a weapon, and prevent an unecessary
hit to performance caused by having an unused evidence system running in qb-policejob.
Removing Existing Server Events
Next, we will need to access our qb-policejob/server/main.lua
and remove the following events which are
used in the default qb-policejob evidence system. It is important to clear all of these events so that they
do not cause errors by accidentally being triggered by events in r14-evidence, and conversley, triggering events
in r14-evidence. Please use CTRL-F to search for, and entirely remove, these networked event handlers.
If you have resources which are cloned versions of qb-policejob, you may need to search them for events with these names as well!
'evidence:server:UpdateStatus'
'evidence:server:CreateBloodDrop'
'evidence:server:CreateFingerDrop'
'evidence:server:ClearBlooddrops'
'evidence:server:AddBlooddropToInventory'
'evidence:server:AddFingerprintToInventory'
'evidence:server:CreateCasing'
'evidence:server:ClearCasings'
'evidence:server:AddCasingToInventory'
Removing Existing Server Callbacks
We will need to remove the police:GetPlayerStatus
callback as well from our qb-policejob/server/main.lua
file.
Because we want this callback available for the Check Status radial menu option, it will need to be moved to r14-evidence
so that it can properly supply status effects to the client using it.
QBCore.Functions.CreateCallback('police:GetPlayerStatus', function(_, cb, playerId)
local Player = QBCore.Functions.GetPlayer(playerId)
local statList = {}
if Player then
if PlayerStatus[Player.PlayerData.source] and next(PlayerStatus[Player.PlayerData.source]) then
for k in pairs(PlayerStatus[Player.PlayerData.source]) do
statList[#statList+1] = PlayerStatus[Player.PlayerData.source][k].text
end
end
end
cb(statList)
end)
Removing Existing Server Commands
Lastly we will need to remove the 'clearblood'
and 'clearcasings'
commands from our qb-policejob server
script as these have been replaced by a combined 'clearevidence'
command in r14-evidence. Once we have done this,
we will finally need to remove the 'takedna'
command, as the new resource now allows police to use qb-target in
order to collect evidence versus a command.
QBCore.Commands.Add("clearblood", Lang:t("commands.clearblood"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("evidence:client:ClearBlooddropsInArea", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("clearcasings", Lang:t("commands.clear_casign"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("evidence:client:ClearCasingsInArea", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("takedna", Lang:t("commands.takedna"), {{name = "id", help = Lang:t('info.player_id')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local OtherPlayer = QBCore.Functions.GetPlayer(tonumber(args[1]))
if not OtherPlayer or Player.PlayerData.job.name ~= "police" or not Player.PlayerData.job.onduty then return end
if Player.Functions.RemoveItem("empty_evidence_bag", 1) then
local info = {
label = Lang:t('info.dna_sample'),
type = "dna",
dnalabel = DnaHash(OtherPlayer.PlayerData.citizenid)
}
if not Player.Functions.AddItem("filled_evidence_bag", 1, false, info) then return end
TriggerClientEvent("inventory:client:ItemBox", src, QBCore.Shared.Items["filled_evidence_bag"], "add")
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.have_evidence_bag"), "error")
end
end)
At this point we have completed the modification of our qb-policejob script and can now continue with our installation process!
Preconfigured Server File
If you are use a recent version of qb-core and a stock qb-policejob, you may be able to use the modified version of qb-policejob/server/main.lua
below that comes with
all of these these events plus evidence-related functions and variables removed. If you have custom code in your qb-policejob/server/main.lua
, please follow the process
bove for modifying your sever code!
This code is current as of 4/1/2023, it will not contain updates more recent than this, and may not be compatible with older version of qb-policejob!
-- Variables
local Plates = {}
local Objects = {}
local QBCore = exports['qb-core']:GetCoreObject()
local updatingCops = false
-- Functions
local function UpdateBlips()
local dutyPlayers = {}
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and (v.PlayerData.job.name == "police" or v.PlayerData.job.name == "ambulance") and v.PlayerData.job.onduty then
local coords = GetEntityCoords(GetPlayerPed(v.PlayerData.source))
local heading = GetEntityHeading(GetPlayerPed(v.PlayerData.source))
dutyPlayers[#dutyPlayers+1] = {
source = v.PlayerData.source,
label = v.PlayerData.metadata["callsign"],
job = v.PlayerData.job.name,
location = {
x = coords.x,
y = coords.y,
z = coords.z,
w = heading
}
}
end
end
TriggerClientEvent("police:client:UpdateBlips", -1, dutyPlayers)
end
local function CreateObjectId()
if Objects then
local objectId = math.random(10000, 99999)
while Objects[objectId] do
objectId = math.random(10000, 99999)
end
return objectId
else
local objectId = math.random(10000, 99999)
return objectId
end
end
local function IsVehicleOwned(plate)
local result = MySQL.scalar.await('SELECT plate FROM player_vehicles WHERE plate = ?', {plate})
return result
end
local function GetCurrentCops()
local amount = 0
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == "police" and v.PlayerData.job.onduty then
amount += 1
end
end
return amount
end
local function DnaHash(s)
local h = string.gsub(s, ".", function(c)
return string.format("%02x", string.byte(c))
end)
return h
end
-- Commands
QBCore.Commands.Add("spikestrip", Lang:t("commands.place_spike"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent('police:client:SpawnSpikeStrip', src)
end
end)
QBCore.Commands.Add("grantlicense", Lang:t("commands.license_grant"), {{name = "id", help = Lang:t('info.player_id')}, {name = "license", help = Lang:t('info.license_type')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.grade.level >= Config.LicenseRank then
if args[2] == "driver" or args[2] == "weapon" then
local SearchedPlayer = QBCore.Functions.GetPlayer(tonumber(args[1]))
if not SearchedPlayer then return end
local licenseTable = SearchedPlayer.PlayerData.metadata["licences"]
if licenseTable[args[2]] then
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.license_already"), "error")
return
end
licenseTable[args[2]] = true
SearchedPlayer.Functions.SetMetaData("licences", licenseTable)
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("success.granted_license"), "success")
TriggerClientEvent('QBCore:Notify', src, Lang:t("success.grant_license"), "success")
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.error_license_type"), "error")
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.rank_license"), "error")
end
end)
QBCore.Commands.Add("revokelicense", Lang:t("commands.license_revoke"), {{name = "id", help = Lang:t('info.player_id')}, {name = "license", help = Lang:t('info.license_type')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.grade.level >= Config.LicenseRank then
if args[2] == "driver" or args[2] == "weapon" then
local SearchedPlayer = QBCore.Functions.GetPlayer(tonumber(args[1]))
if not SearchedPlayer then return end
local licenseTable = SearchedPlayer.PlayerData.metadata["licences"]
if not licenseTable[args[2]] then
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.error_license"), "error")
return
end
licenseTable[args[2]] = false
SearchedPlayer.Functions.SetMetaData("licences", licenseTable)
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("error.revoked_license"), "error")
TriggerClientEvent('QBCore:Notify', src, Lang:t("success.revoke_license"), "success")
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.error_license"), "error")
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.rank_revoke"), "error")
end
end)
QBCore.Commands.Add("pobject", Lang:t("commands.place_object"), {{name = "type",help = Lang:t("info.poobject_object")}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local type = args[1]:lower()
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
if type == "cone" then
TriggerClientEvent("police:client:spawnCone", src)
elseif type == "barrier" then
TriggerClientEvent("police:client:spawnBarrier", src)
elseif type == "roadsign" then
TriggerClientEvent("police:client:spawnRoadSign", src)
elseif type == "tent" then
TriggerClientEvent("police:client:spawnTent", src)
elseif type == "light" then
TriggerClientEvent("police:client:spawnLight", src)
elseif type == "delete" then
TriggerClientEvent("police:client:deleteObject", src)
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("cuff", Lang:t("commands.cuff_player"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:CuffPlayer", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("escort", Lang:t("commands.escort"), {}, false, function(source)
local src = source
TriggerClientEvent("police:client:EscortPlayer", src)
end)
QBCore.Commands.Add("callsign", Lang:t("commands.callsign"), {{name = "name", help = Lang:t('info.callsign_name')}}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
Player.Functions.SetMetaData("callsign", table.concat(args, " "))
end)
QBCore.Commands.Add("jail", Lang:t("commands.jail_player"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:JailPlayer", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("unjail", Lang:t("commands.unjail_player"), {{name = "id", help = Lang:t('info.player_id')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
local playerId = tonumber(args[1])
TriggerClientEvent("prison:client:UnjailPerson", playerId)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("seizecash", Lang:t("commands.seizecash"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:SeizeCash", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("sc", Lang:t("commands.softcuff"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:CuffPlayerSoft", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("cam", Lang:t("commands.camera"), {{name = "camid", help = Lang:t('info.camera_id')}}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:ActiveCamera", src, tonumber(args[1]))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("flagplate", Lang:t("commands.flagplate"), {{name = "plate", help = Lang:t('info.plate_number')}, {name = "reason", help = Lang:t('info.flag_reason')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
local reason = {}
for i = 2, #args, 1 do
reason[#reason+1] = args[i]
end
Plates[args[1]:upper()] = {
isflagged = true,
reason = table.concat(reason, " ")
}
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.vehicle_flagged", {vehicle = args[1]:upper(), reason = table.concat(reason, " ")}))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("unflagplate", Lang:t("commands.unflagplate"), {{name = "plate", help = Lang:t('info.plate_number')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
if Plates and Plates[args[1]:upper()] then
if Plates[args[1]:upper()].isflagged then
Plates[args[1]:upper()].isflagged = false
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.unflag_vehicle", {vehicle = args[1]:upper()}))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.vehicle_not_flag"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.vehicle_not_flag"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("plateinfo", Lang:t("commands.plateinfo"), {{name = "plate", help = Lang:t('info.plate_number')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
if Plates and Plates[args[1]:upper()] then
if Plates[args[1]:upper()].isflagged then
TriggerClientEvent('QBCore:Notify', src, Lang:t('success.vehicle_flagged', {plate = args[1]:upper(), reason = Plates[args[1]:upper()].reason}), 'success')
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.vehicle_not_flag"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.vehicle_not_flag"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("depot", Lang:t("commands.depot"), {{name = "price", help = Lang:t('info.impound_price')}}, false, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:ImpoundVehicle", src, false, tonumber(args[1]))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("impound", Lang:t("commands.impound"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:ImpoundVehicle", src, true)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("paytow", Lang:t("commands.paytow"), {{name = "id", help = Lang:t('info.player_id')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
local playerId = tonumber(args[1])
local OtherPlayer = QBCore.Functions.GetPlayer(playerId)
if OtherPlayer then
if OtherPlayer.PlayerData.job.name == "tow" then
OtherPlayer.Functions.AddMoney("bank", 500, "police-tow-paid")
TriggerClientEvent('QBCore:Notify', OtherPlayer.PlayerData.source, Lang:t("success.tow_paid"), 'success')
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.tow_driver_paid"))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_towdriver"), 'error')
end
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("paylawyer", Lang:t("commands.paylawyer"), {{name = "id",help = Lang:t('info.player_id')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" or Player.PlayerData.job.name == "judge" then
local playerId = tonumber(args[1])
local OtherPlayer = QBCore.Functions.GetPlayer(playerId)
if not OtherPlayer then return end
if OtherPlayer.PlayerData.job.name == "lawyer" then
OtherPlayer.Functions.AddMoney("bank", 500, "police-lawyer-paid")
TriggerClientEvent('QBCore:Notify', OtherPlayer.PlayerData.source, Lang:t("success.tow_paid"), 'success')
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.paid_lawyer"))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_lawyer"), "error")
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add('fine', Lang:t("commands.fine"), {{name = 'id', help = Lang:t('info.player_id')}, {name = 'amount', help = Lang:t('info.amount')}}, false, function(source, args)
local biller = QBCore.Functions.GetPlayer(source)
local billed = QBCore.Functions.GetPlayer(tonumber(args[1]))
local amount = tonumber(args[2])
if biller.PlayerData.job.name == "police" then
if billed ~= nil then
if biller.PlayerData.citizenid ~= billed.PlayerData.citizenid then
if amount and amount > 0 then
if billed.Functions.RemoveMoney('bank', amount, "paid-fine") then
TriggerClientEvent('QBCore:Notify', source, Lang:t("info.fine_issued"), 'success')
TriggerClientEvent('QBCore:Notify', billed.PlayerData.source, Lang:t("info.received_fine"))
exports['qb-management']:AddMoney(biller.PlayerData.job.name, amount)
elseif billed.Functions.RemoveMoney('cash', amount, "paid-fine") then
TriggerClientEvent('QBCore:Notify', source, Lang:t("info.fine_issued"), 'success')
TriggerClientEvent('QBCore:Notify', billed.PlayerData.source, Lang:t("info.received_fine"))
exports['qb-management']:AddMoney(biller.PlayerData.job.name, amount)
else
MySQL.Async.insert('INSERT INTO phone_invoices (citizenid, amount, society, sender, sendercitizenid) VALUES (?, ?, ?, ?, ?)',{billed.PlayerData.citizenid, amount, biller.PlayerData.job.name, biller.PlayerData.charinfo.firstname, biller.PlayerData.citizenid}, function(id)
if id then
TriggerClientEvent('qb-phone:client:AcceptorDenyInvoice', billed.PlayerData.source, id, biller.PlayerData.charinfo.firstname, biller.PlayerData.job.name, biller.PlayerData.citizenid, amount, GetInvokingResource())
end
end)
TriggerClientEvent('qb-phone:RefreshPhone', billed.PlayerData.source)
end
else
TriggerClientEvent('QBCore:Notify', source, Lang:t("error.amount_higher"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', source, Lang:t("error.fine_yourself"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', source, Lang:t("error.not_online"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', source, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("anklet", Lang:t("commands.anklet"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:CheckDistance", src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("ankletlocation", Lang:t("commands.ankletlocation"), {{name = "cid", help = Lang:t('info.citizen_id')}}, true, function(source, args)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
local citizenid = args[1]
local Target = QBCore.Functions.GetPlayerByCitizenId(citizenid)
if not Target then return end
if Target.PlayerData.metadata["tracker"] then
TriggerClientEvent("police:client:SendTrackerLocation", Target.PlayerData.source, src)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.no_anklet"), 'error')
end
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
QBCore.Commands.Add("takedrivinglicense", Lang:t("commands.drivinglicense"), {}, false, function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then
TriggerClientEvent("police:client:SeizeDriverLicense", source)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.on_duty_police_only"), 'error')
end
end)
RegisterNetEvent('police:server:SendTrackerLocation', function(coords, requestId)
local Target = QBCore.Functions.GetPlayer(source)
local msg = Lang:t('info.target_location', {firstname = Target.PlayerData.charinfo.firstname, lastname = Target.PlayerData.charinfo.lastname})
local alertData = {
title = Lang:t('info.anklet_location'),
coords = {
x = coords.x,
y = coords.y,
z = coords.z
},
description = msg
}
TriggerClientEvent("police:client:TrackerMessage", requestId, msg, coords)
TriggerClientEvent("qb-phone:client:addPoliceAlert", requestId, alertData)
end)
QBCore.Commands.Add('911p', Lang:t("commands.police_report"), {{name='message', help= Lang:t("commands.message_sent")}}, false, function(source, args)
local src = source
local message
if args[1] then message = table.concat(args, " ") else message = Lang:t("commands.civilian_call") end
local ped = GetPlayerPed(src)
local coords = GetEntityCoords(ped)
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == 'police' and v.PlayerData.job.onduty then
local alertData = {title = Lang:t("commands.emergency_call"), coords = {x = coords.x, y = coords.y, z = coords.z}, description = message}
TriggerClientEvent("qb-phone:client:addPoliceAlert", v.PlayerData.source, alertData)
TriggerClientEvent('police:client:policeAlert', v.PlayerData.source, coords, message)
end
end
end)
-- Items
QBCore.Functions.CreateUseableItem("handcuffs", function(source)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player.Functions.GetItemByName("handcuffs") then return end
TriggerClientEvent("police:client:CuffPlayerSoft", src)
end)
QBCore.Functions.CreateUseableItem("moneybag", function(source, item)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or not Player.Functions.GetItemByName("moneybag") or not item.info or item.info == "" or Player.PlayerData.job.name == "police" or not Player.Functions.RemoveItem("moneybag", 1, item.slot) then return end
Player.Functions.AddMoney("cash", tonumber(item.info.cash), "used-moneybag")
end)
-- Callbacks
QBCore.Functions.CreateCallback('police:server:isPlayerDead', function(_, cb, playerId)
local Player = QBCore.Functions.GetPlayer(playerId)
cb(Player.PlayerData.metadata["isdead"])
end)
QBCore.Functions.CreateCallback('police:IsSilencedWeapon', function(source, cb, weapon)
local Player = QBCore.Functions.GetPlayer(source)
local itemInfo = Player.Functions.GetItemByName(QBCore.Shared.Weapons[weapon]["name"])
local retval = false
if itemInfo then
if itemInfo.info and itemInfo.info.attachments then
for k in pairs(itemInfo.info.attachments) do
if itemInfo.info.attachments[k].component == "COMPONENT_AT_AR_SUPP_02" or
itemInfo.info.attachments[k].component == "COMPONENT_AT_AR_SUPP" or
itemInfo.info.attachments[k].component == "COMPONENT_AT_PI_SUPP_02" or
itemInfo.info.attachments[k].component == "COMPONENT_AT_PI_SUPP" then
retval = true
end
end
end
end
cb(retval)
end)
QBCore.Functions.CreateCallback('police:GetDutyPlayers', function(_, cb)
local dutyPlayers = {}
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == "police" and v.PlayerData.job.onduty then
dutyPlayers[#dutyPlayers+1] = {
source = v.PlayerData.source,
label = v.PlayerData.metadata["callsign"],
job = v.PlayerData.job.name
}
end
end
cb(dutyPlayers)
end)
QBCore.Functions.CreateCallback('police:GetImpoundedVehicles', function(_, cb)
local vehicles = {}
MySQL.query('SELECT * FROM player_vehicles WHERE state = ?', {2}, function(result)
if result[1] then
vehicles = result
end
cb(vehicles)
end)
end)
QBCore.Functions.CreateCallback('police:IsPlateFlagged', function(_, cb, plate)
local retval = false
if Plates and Plates[plate] then
if Plates[plate].isflagged then
retval = true
end
end
cb(retval)
end)
QBCore.Functions.CreateCallback('police:GetCops', function(_, cb)
local amount = 0
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == "police" and v.PlayerData.job.onduty then
amount = amount + 1
end
end
cb(amount)
end)
QBCore.Functions.CreateCallback('police:server:IsPoliceForcePresent', function(_, cb)
local retval = false
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == "police" and v.PlayerData.job.grade.level >= 2 then
retval = true
break
end
end
cb(retval)
end)
-- Events
AddEventHandler('onResourceStart', function(resourceName)
if resourceName == GetCurrentResourceName() then
CreateThread(function()
MySQL.query("DELETE FROM stashitems WHERE stash = 'policetrash'")
end)
end
end)
RegisterNetEvent('police:server:policeAlert', function(text)
local src = source
local ped = GetPlayerPed(src)
local coords = GetEntityCoords(ped)
local players = QBCore.Functions.GetQBPlayers()
for _, v in pairs(players) do
if v and v.PlayerData.job.name == 'police' and v.PlayerData.job.onduty then
local alertData = {title = Lang:t('info.new_call'), coords = {x = coords.x, y = coords.y, z = coords.z}, description = text}
TriggerClientEvent("qb-phone:client:addPoliceAlert", v.PlayerData.source, alertData)
TriggerClientEvent('police:client:policeAlert', v.PlayerData.source, coords, text)
end
end
end)
RegisterNetEvent('police:server:TakeOutImpound', function(plate, garage)
local src = source
local playerPed = GetPlayerPed(src)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = Config.Locations["impound"][garage]
if #(playerCoords - targetCoords) > 10.0 then return DropPlayer(src, "Attempted exploit abuse") end
MySQL.update('UPDATE player_vehicles SET state = ? WHERE plate = ?', {0, plate})
TriggerClientEvent('QBCore:Notify', src, Lang:t("success.impound_vehicle_removed"), 'success')
end)
RegisterNetEvent('police:server:CuffPlayer', function(playerId, isSoftcuff)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(src)
local CuffedPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not CuffedPlayer or (not Player.Functions.GetItemByName("handcuffs") and Player.PlayerData.job.name ~= "police") then return end
TriggerClientEvent("police:client:GetCuffed", CuffedPlayer.PlayerData.source, Player.PlayerData.source, isSoftcuff)
end)
RegisterNetEvent('police:server:EscortPlayer', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(source)
local EscortPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not EscortPlayer then return end
if (Player.PlayerData.job.name == "police" or Player.PlayerData.job.name == "ambulance") or (EscortPlayer.PlayerData.metadata["ishandcuffed"] or EscortPlayer.PlayerData.metadata["isdead"] or EscortPlayer.PlayerData.metadata["inlaststand"]) then
TriggerClientEvent("police:client:GetEscorted", EscortPlayer.PlayerData.source, Player.PlayerData.source)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_cuffed_dead"), 'error')
end
end)
RegisterNetEvent('police:server:KidnapPlayer', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(source)
local EscortPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not EscortPlayer then return end
if EscortPlayer.PlayerData.metadata["ishandcuffed"] or EscortPlayer.PlayerData.metadata["isdead"] or EscortPlayer.PlayerData.metadata["inlaststand"] then
TriggerClientEvent("police:client:GetKidnappedTarget", EscortPlayer.PlayerData.source, Player.PlayerData.source)
TriggerClientEvent("police:client:GetKidnappedDragger", Player.PlayerData.source, EscortPlayer.PlayerData.source)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_cuffed_dead"), 'error')
end
end)
RegisterNetEvent('police:server:SetPlayerOutVehicle', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local EscortPlayer = QBCore.Functions.GetPlayer(playerId)
if not QBCore.Functions.GetPlayer(src) or not EscortPlayer then return end
if EscortPlayer.PlayerData.metadata["ishandcuffed"] or EscortPlayer.PlayerData.metadata["isdead"] then
TriggerClientEvent("police:client:SetOutVehicle", EscortPlayer.PlayerData.source)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_cuffed_dead"), 'error')
end
end)
RegisterNetEvent('police:server:PutPlayerInVehicle', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local EscortPlayer = QBCore.Functions.GetPlayer(playerId)
if not QBCore.Functions.GetPlayer(src) or not EscortPlayer then return end
if EscortPlayer.PlayerData.metadata["ishandcuffed"] or EscortPlayer.PlayerData.metadata["isdead"] then
TriggerClientEvent("police:client:PutInVehicle", EscortPlayer.PlayerData.source)
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.not_cuffed_dead"), 'error')
end
end)
RegisterNetEvent('police:server:BillPlayer', function(playerId, price)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(src)
local OtherPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not OtherPlayer or Player.PlayerData.job.name ~= "police" then return end
OtherPlayer.Functions.RemoveMoney("bank", price, "paid-bills")
exports['qb-management']:AddMoney("police", price)
TriggerClientEvent('QBCore:Notify', OtherPlayer.PlayerData.source, Lang:t("info.fine_received", {fine = price}))
end)
RegisterNetEvent('police:server:JailPlayer', function(playerId, time)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(src)
local OtherPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not OtherPlayer or Player.PlayerData.job.name ~= "police" then return end
local currentDate = os.date("*t")
if currentDate.day == 31 then
currentDate.day = 30
end
OtherPlayer.Functions.SetMetaData("injail", time)
OtherPlayer.Functions.SetMetaData("criminalrecord", {
["hasRecord"] = true,
["date"] = currentDate
})
TriggerClientEvent("police:client:SendToJail", OtherPlayer.PlayerData.source, time)
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.sent_jail_for", {time = time}))
end)
RegisterNetEvent('police:server:SetHandcuffStatus', function(isHandcuffed)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player then
Player.Functions.SetMetaData("ishandcuffed", isHandcuffed)
end
end)
RegisterNetEvent('heli:spotlight', function(state)
local serverID = source
TriggerClientEvent('heli:spotlight', -1, serverID, state)
end)
-- RegisterNetEvent('police:server:FlaggedPlateTriggered', function(camId, plate, street1, street2, blipSettings)
-- local src = source
-- for k, v in pairs(QBCore.Functions.GetPlayers()) do
-- local Player = QBCore.Functions.GetPlayer(v)
-- if Player then
-- if (Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty) then
-- if street2 then
-- TriggerClientEvent("112:client:SendPoliceAlert", v, "flagged", {
-- camId = camId,
-- plate = plate,
-- streetLabel = street1 .. " " .. street2
-- }, blipSettings)
-- else
-- TriggerClientEvent("112:client:SendPoliceAlert", v, "flagged", {
-- camId = camId,
-- plate = plate,
-- streetLabel = street1
-- }, blipSettings)
-- end
-- end
-- end
-- end
-- end)
RegisterNetEvent('police:server:SearchPlayer', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local SearchedPlayer = QBCore.Functions.GetPlayer(playerId)
if not QBCore.Functions.GetPlayer(src) or not SearchedPlayer then return end
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.cash_found", {cash = SearchedPlayer.PlayerData.money["cash"]}))
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("info.being_searched"))
end)
RegisterNetEvent('police:server:SeizeCash', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(src)
local SearchedPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not SearchedPlayer then return end
local moneyAmount = SearchedPlayer.PlayerData.money["cash"]
local info = { cash = moneyAmount }
SearchedPlayer.Functions.RemoveMoney("cash", moneyAmount, "police-cash-seized")
Player.Functions.AddItem("moneybag", 1, false, info)
TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["moneybag"], "add")
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("info.cash_confiscated"))
end)
RegisterNetEvent('police:server:SeizeDriverLicense', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local SearchedPlayer = QBCore.Functions.GetPlayer(playerId)
if not QBCore.Functions.GetPlayer(src) or not SearchedPlayer then return end
local driverLicense = SearchedPlayer.PlayerData.metadata["licences"]["driver"]
if driverLicense then
local licenses = {["driver"] = false, ["business"] = SearchedPlayer.PlayerData.metadata["licences"]["business"]}
SearchedPlayer.Functions.SetMetaData("licences", licenses)
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("info.driving_license_confiscated"))
else
TriggerClientEvent('QBCore:Notify', src, Lang:t("error.no_driver_license"), 'error')
end
end)
RegisterNetEvent('police:server:RobPlayer', function(playerId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Player = QBCore.Functions.GetPlayer(src)
local SearchedPlayer = QBCore.Functions.GetPlayer(playerId)
if not Player or not SearchedPlayer then return end
local money = SearchedPlayer.PlayerData.money["cash"]
Player.Functions.AddMoney("cash", money, "police-player-robbed")
SearchedPlayer.Functions.RemoveMoney("cash", money, "police-player-robbed")
TriggerClientEvent('QBCore:Notify', SearchedPlayer.PlayerData.source, Lang:t("info.cash_robbed", {money = money}))
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t("info.stolen_money", {stolen = money}))
end)
RegisterNetEvent('police:server:UpdateBlips', function()
-- KEEP FOR REF BUT NOT NEEDED ANYMORE.
end)
RegisterNetEvent('police:server:spawnObject', function(type)
local src = source
local objectId = CreateObjectId()
Objects[objectId] = type
TriggerClientEvent("police:client:spawnObject", src, objectId, type, src)
end)
RegisterNetEvent('police:server:deleteObject', function(objectId)
TriggerClientEvent('police:client:removeObject', -1, objectId)
end)
RegisterNetEvent('police:server:Impound', function(plate, fullImpound, price, body, engine, fuel)
local src = source
price = price and price or 0
if IsVehicleOwned(plate) then
if not fullImpound then
MySQL.query(
'UPDATE player_vehicles SET state = ?, depotprice = ?, body = ?, engine = ?, fuel = ? WHERE plate = ?',
{0, price, body, engine, fuel, plate})
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.vehicle_taken_depot", {price = price}))
else
MySQL.query(
'UPDATE player_vehicles SET state = ?, body = ?, engine = ?, fuel = ? WHERE plate = ?',
{2, body, engine, fuel, plate})
TriggerClientEvent('QBCore:Notify', src, Lang:t("info.vehicle_seized"))
end
end
end)
RegisterNetEvent('police:server:UpdateCurrentCops', function()
local amount = 0
local players = QBCore.Functions.GetQBPlayers()
if updatingCops then return end
updatingCops = true
for _, v in pairs(players) do
if v and v.PlayerData.job.name == "police" and v.PlayerData.job.onduty then
amount += 1
end
end
TriggerClientEvent("police:SetCopCount", -1, amount)
updatingCops = false
end)
RegisterNetEvent('police:server:showFingerprint', function(playerId)
local src = source
TriggerClientEvent('police:client:showFingerprint', playerId, src)
TriggerClientEvent('police:client:showFingerprint', src, playerId)
end)
RegisterNetEvent('police:server:showFingerprintId', function(sessionId)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
local fid = Player.PlayerData.metadata["fingerprint"]
TriggerClientEvent('police:client:showFingerprintId', sessionId, fid)
TriggerClientEvent('police:client:showFingerprintId', src, fid)
end)
RegisterNetEvent('police:server:SetTracker', function(targetId)
local src = source
local playerPed = GetPlayerPed(src)
local targetPed = GetPlayerPed(targetId)
local playerCoords = GetEntityCoords(playerPed)
local targetCoords = GetEntityCoords(targetPed)
if #(playerCoords - targetCoords) > 2.5 then return DropPlayer(src, "Attempted exploit abuse") end
local Target = QBCore.Functions.GetPlayer(targetId)
if not QBCore.Functions.GetPlayer(src) or not Target then return end
local TrackerMeta = Target.PlayerData.metadata["tracker"]
if TrackerMeta then
Target.Functions.SetMetaData("tracker", false)
TriggerClientEvent('QBCore:Notify', targetId, Lang:t("success.anklet_taken_off"), 'success')
TriggerClientEvent('QBCore:Notify', src, Lang:t("success.took_anklet_from", {firstname = Target.PlayerData.charinfo.firstname, lastname = Target.PlayerData.charinfo.lastname}), 'success')
TriggerClientEvent('police:client:SetTracker', targetId, false)
else
Target.Functions.SetMetaData("tracker", true)
TriggerClientEvent('QBCore:Notify', targetId, Lang:t("success.put_anklet"), 'success')
TriggerClientEvent('QBCore:Notify', src, Lang:t("success.put_anklet_on", {firstname = Target.PlayerData.charinfo.firstname, lastname = Target.PlayerData.charinfo.lastname}), 'success')
TriggerClientEvent('police:client:SetTracker', targetId, true)
end
end)
RegisterNetEvent('police:server:SyncSpikes', function(table)
TriggerClientEvent('police:client:SyncSpikes', -1, table)
end)
-- Threads
CreateThread(function()
while true do
Wait(1000 * 60 * 10)
local curCops = GetCurrentCops()
TriggerClientEvent("police:SetCopCount", -1, curCops)
end
end)
CreateThread(function()
while true do
Wait(5000)
UpdateBlips()
end
end)